package org.truenewx.tnxjee.webmvc.method.support;

import jakarta.servlet.http.HttpServletRequest;
import org.springframework.core.MethodParameter;
import org.springframework.util.Assert;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.context.request.ServletWebRequest;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.truenewx.tnxjee.model.spec.Terminal;
import org.truenewx.tnxjee.model.spec.enums.Program;
import org.truenewx.tnxjee.service.reminder.manager.ReminderManager;
import org.truenewx.tnxjee.service.reminder.model.ReminderDescriptor;
import org.truenewx.tnxjee.web.context.SpringWebContext;
import org.truenewx.tnxjee.web.util.WebUtil;
import org.truenewx.tnxjee.webmvc.response.RpcResponse;
import org.truenewx.tnxjee.webmvc.response.reminder.resolver.ReminderMessageResolver;
import org.truenewx.tnxjee.webmvc.security.web.RestResponseResultDecider;

import java.util.List;
import java.util.Locale;

/**
 * 转义处理方法结果值处理器
 */
public class EscapeHandlerMethodReturnValueHandler implements HandlerMethodReturnValueHandler {

    private HandlerMethodReturnValueHandler delegate;
    private RestResponseResultDecider restResponseResultDecider;
    private ReminderMessageResolver reminderMessageResolver;

    public EscapeHandlerMethodReturnValueHandler(HandlerMethodReturnValueHandler delegate,
            RestResponseResultDecider restResponseResultDecider,
            ReminderMessageResolver reminderMessageResolver) {
        Assert.notNull(delegate, "The delegate must be not null");
        this.delegate = delegate;
        this.restResponseResultDecider = restResponseResultDecider;
        this.reminderMessageResolver = reminderMessageResolver;
    }

    @Override
    public boolean supportsReturnType(MethodParameter returnType) {
        return this.delegate.supportsReturnType(returnType);
    }

    @Override
    public void handleReturnValue(Object returnValue, MethodParameter returnType,
            ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
        if (MethodParameterEscapeProcessor.INSTANCE.supports(returnType)) {
            if (webRequest instanceof ServletWebRequest) {
                HttpServletRequest request = ((ServletWebRequest) webRequest).getRequest();
                Terminal terminal = WebUtil.getRequestTerminal(request);
                if (terminal.getProgram() == Program.NATIVE) { // 原生应用才需要反转义
                    returnValue = MethodParameterEscapeProcessor.INSTANCE.escape(returnValue, true);
                }
            }
        }
        if (this.restResponseResultDecider != null) {
            HttpServletRequest request = SpringWebContext.getRequest();
            if (request != null && this.restResponseResultDecider.supports(request)) {
                returnValue = this.restResponseResultDecider.getReturnBody(returnValue);
            }
        } else {
            RpcResponse rpcResponse = RpcResponse.ok(returnValue);
            List<ReminderDescriptor> reminderDescriptors = ReminderManager.getAndClear();
            if (!reminderDescriptors.isEmpty()) {
                Locale locale = webRequest.getLocale();
                rpcResponse.setReminders(reminderDescriptors.stream()
                        .map(descriptor -> this.reminderMessageResolver.resolve(descriptor, locale))
                        .toList());
            }
            returnValue = rpcResponse;
        }
        this.delegate.handleReturnValue(returnValue, returnType, mavContainer, webRequest);
    }

}
